/**
 * package Environnement
 */
package ca.csf.dfc.poo.bots;

import java.util.HashMap;
import java.util.Random;

import ca.csf.dfc.poo.env.Case;
import ca.csf.dfc.poo.env.Direction;
import ca.csf.dfc.poo.env.Environnement;
import ca.csf.dfc.poo.env.Position;

/**
 * Classe abstraite représentant un objet Robot
 * 
 * @author Ali Barkaoui, Francis Beaudoin, Pierre Cloutier & Camille Besse
 */
public abstract class Robot
{
    /**
     * La position du robot.
     */
    private Position m_Position;

    /**
     * La valeur de la récompense accumulée par le robot.
     */
    private int m_RecompenseAccumule;

    /**
     * Générateur de nombre aléatoires
     */
    protected Random m_r;
    
    // ------------------------------------------------------
    // ************* Constructeurs d'initialisation *********
    /**
     * Constructeur d'initialisation. Initialise un objet Robot avec son identifiant calculé et sa position passée en
     * paramètre
     * 
     * @param p_position
     *            position du robot
     */
    public Robot(Random p_r, Environnement p_Environnement)
    {
        m_r = p_r;
        boolean caseEstValide = false;
    	
        
        while(caseEstValide == false)
        {
        	Position maPosition = new Position(this.m_r.nextInt(p_Environnement.getHeight()), this.m_r.nextInt(p_Environnement.getWidth()));
        	
        	if(p_Environnement.caseValide(maPosition) == true)
        	{
        		caseEstValide = true;
        	}
        }
    }
    
    
    /**
     * Constructeur d'initialisation. Initialise un objet Robot avec son identifiant calculé et sa position passée en
     * paramètre
     * 
     * @param p_position
     *            position du robot
     */
    public Robot(Position p_position, Random p_r)
    {
        this.m_Position = p_position;
        m_r = p_r;
    }

    // ------------------------------------------------------
    // ************* Sets et Gets *****************************
    /**
     * Retourne la récompense accumulée.
     * 
     * @return this.m_RecompenseAccumule la récompense accumulée
     */
    public int getAccReward()
    {
        return this.m_RecompenseAccumule;
    }

    /**
     * Pour modifier la récompense accumulée
     * 
     * @param p_recompense
     *            Nouvelle valeur ajoutée.
     */
    public void addAccReward(int p_recompense)
    {
        this.m_RecompenseAccumule += p_recompense;
    }

    /**
     * Retourne la position actuelle.
     * 
     * @return this.m_Position la position
     */
    public Position getPosition()
    {
        return this.m_Position;
    }

    /**
     * Pour modifier la position
     * 
     * @param p_position
     *            Nouvelle valeur.
     */
    public void setPosition(Position p_position)
    {
        this.m_Position = p_position;
    }

    /**
     * Fonction abstraite Retourne l'image du robot dans l'environnement
     * 
     * @return image du robot
     */
    public abstract String getImage();

    
    /**
     * Fonction abstraite Déplace le robot dans l'environnement
     * 
     * @param p_Environnement
     *            : L'environnement
     * @throws RobotException
     */
    public abstract Direction decide(HashMap<Direction,Case> p_possibles);

    /**
     * Fonction qui effectue le déplacement du robot selon la direction
     * 
     * @param p_Direction
     *            : Direction du déplacement
     */
    public void doIt(Direction p_Direction)
    {
        this.m_Position = this.m_Position.relativePos(p_Direction);
    }

    /**
     * Affiche la position du robot et ses récompenses accumulées
     */
    public String toString()
    {
        String retour = "";

        retour = "Robot : " + "\n" + "Position X: " + this.getPosition().m_x + "\n"
                + "Position Y: " + this.getPosition().m_y + "\n" + "Récompense accumulé: "
                + this.getAccReward() + "\n";

        return retour;
    }
}
